home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / forth / pfe-0.000 / pfe-0 / pfe-0.9.13 / src / lined.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-17  |  7.1 KB  |  390 lines

  1. /*
  2.  * This file is part of the portable Forth environment written in ANSI C.
  3.  * Copyright (C) 1995  Dirk Uwe Zoller
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13.  * See the GNU Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * This file is version 0.9.13 of 17-July-95
  20.  * Check for the latest version of this package via anonymous ftp at
  21.  *    roxi.rz.fht-mannheim.de:/pub/languages/forth/pfe-VERSION.tar.gz
  22.  * or    sunsite.unc.edu:/pub/languages/forth/pfe-VERSION.tar.gz
  23.  * or    ftp.cygnus.com:/pub/forth/pfe-VERSION.tar.gz
  24.  *
  25.  * Please direct any comments via internet to
  26.  *    duz@roxi.rz.fht-mannheim.de.
  27.  * Thank You.
  28.  */
  29. /*
  30.  * lined.c --- small general purpose line editor
  31.  * (duz 08Jun93)
  32.  */
  33.  
  34. #include "forth.h"
  35. #include "support.h"
  36. #include "term.h"
  37. #include "lined.h"
  38.  
  39. #include <string.h>
  40. #include <ctype.h>
  41.  
  42. #include "missing.h"
  43.  
  44. /* *INDENT-OFF* */
  45. static void left (int dist)    { while (--dist >= 0) c_goleft (); }
  46. static void right (int dist)    { while (--dist >= 0) c_goright (); }
  47. /* *INDENT-ON* */
  48.  
  49. /* Some shortcuts. All functions in this file work on a "struct lined *l" */
  50. #undef MAX
  51.  
  52. #define P    (l->string)
  53. #define MAX    (l->max_length)
  54. #define H    (l->history)
  55. #define HMAX    (l->history_max)
  56. #define L    (l->length)
  57. #define C    (l->cursor)
  58. #define HL    (l->history_length)
  59. #define HR    (l->history_read)
  60. #define HW    (l->history_write)
  61.  
  62. static void
  63. redisplay (struct lined *l)
  64. {
  65.   int i;
  66.  
  67.   for (i = 0; i < L; i++)
  68.     c_putc_printable (P[i]);
  69.   left (i - C);
  70. }
  71.  
  72. static void
  73. replace_string (struct lined *l, char *s)
  74. {
  75.   int i;
  76.  
  77.   left (C);
  78.   for (i = 0; *s && i < MAX; i++)
  79.     c_putc_printable (P[i] = *s++);
  80.   C = i;
  81.   if (i < L)
  82.     {
  83.       for (; i < L; i++)
  84.     c_putc (' ');
  85.       left (i - C);
  86.     }
  87.   L = C;
  88. }
  89.  
  90. static void
  91. put_history_string (struct lined *l, char *p)
  92. {
  93.   char c;
  94.  
  95.   do
  96.     {
  97.       if (HL < HMAX)
  98.     HL++;
  99.       H[HW++] = c = *p++;
  100.       HW %= HMAX;
  101.     }
  102.   while (c != '\0');
  103.   HR = HW;
  104. }
  105.  
  106. #define NEXT(X)    (X = (X      + 1) % HL)
  107. #define PREV(X)    (X = (X + HL - 1) % HL)
  108.  
  109. static int
  110. get_history_string (struct lined *l, char *p, int n)
  111. {
  112.   int i, r = HR;
  113.  
  114.   for (i = 0; i < n; i++)
  115.     {
  116.       if (r == HW || (*p++ = H[r]) == '\0')
  117.     break;
  118.       NEXT (r);
  119.     }
  120.   return i;
  121. }
  122.  
  123. static int
  124. back_history (struct lined *l)
  125. {
  126.   char buf[0x100];
  127.   int n = HR;
  128.  
  129.   if (HL == 0)
  130.     return 0;
  131.   PREV (n);
  132.   do
  133.     {
  134.       PREV (n);
  135.       if (n == HW)
  136.     return 0;
  137.     }
  138.   while (H[n] != '\0');
  139.   NEXT (n);
  140.   HR = n;
  141.   get_history_string (l, buf, sizeof buf);
  142.   replace_string (l, buf);
  143.   return 1;
  144. }
  145.  
  146. static int
  147. fwd_history (struct lined *l)
  148. {
  149.   char buf[0x100];
  150.   int r = HR;
  151.  
  152.   if (HL == 0)
  153.     return 0;
  154.   for (r = HR; H[r] != '\0'; NEXT (r));
  155.   NEXT (r);
  156.   if (HR == HW)
  157.     return 0;
  158.   HR = r;
  159.   get_history_string (l, buf, sizeof buf);
  160.   replace_string (l, buf);
  161.   return 1;
  162. }
  163.  
  164. static void
  165. insertc (struct lined *l, char c)
  166. {
  167.   int i;
  168.  
  169.   if (l->overtype)
  170.     {
  171.       if (C == L)
  172.     L++;
  173.     }
  174.   else
  175.     for (i = L++; i > C; i--)
  176.       P[i] = P[i - 1];
  177.   c_putc_printable (P[C++] = c);
  178.   if (l->overtype)
  179.     return;
  180.   for (i = C; i < L; i++)
  181.     c_putc_printable (P[i]);
  182.   left (L - C);
  183. }
  184.  
  185. int
  186. lined (struct lined *l, char *dflt)
  187. {
  188.   char *b, buf[0x100];        /* scratchpad to work on */
  189.   int c, i, display = 0;
  190.  
  191.   b = P, P = buf;        /* switch to scratchpad */
  192.   C = L = 0;
  193.   if (dflt)
  194.     replace_string (l, dflt);
  195.   while (L < MAX)
  196.     {
  197.       c = getekey ();
  198.       if (l->caps)
  199.     c = change_case (c);
  200.       switch (c)
  201.     {
  202.     case 'P' - '@':
  203.       c = c_getkey ();
  204.       if (l->caps)
  205.         c = change_case (c);
  206.     default:
  207.       if (c >= 0x100)    /* other function key */
  208.         {
  209.           if (!l->executes || c < EKEY_k1 || EKEY_k0 < c)
  210.         {
  211.           c_bell ();
  212.           break;
  213.         }
  214.           right (L - C);
  215.           c_puts ("\\\n");
  216.           l->executes[c - EKEY_k1] (c - EKEY_k1);
  217.           for (i = 0; i < L; i++)
  218.         c_putc_printable (P[i]);
  219.           left (L - C);
  220.           break;
  221.         }
  222.       if (dflt)
  223.         replace_string (l, "");
  224.       insertc (l, c);
  225.       break;
  226.     case '\t':
  227. #if !NO_COMPLETION
  228.       if (l->complete)
  229.         {
  230.           char cpl[0x100];
  231.  
  232.           store_c_string (P, C, cpl, sizeof cpl);
  233.           if (display)
  234.         {
  235.           extern void cr_ (void);
  236.  
  237.           cr_ ();
  238.           c = l->complete (cpl, cpl, 1);
  239.           cr_ ();
  240.           redisplay (l);
  241.         }
  242.           else
  243.         {
  244.           c = l->complete (cpl, cpl, 0);
  245.           display = 1;
  246.         }
  247.  
  248.           if (c == 0)
  249.         {
  250.           c_bell ();
  251.           continue;
  252.         }
  253.           for (i = C; i < strlen (cpl); i++)
  254.         insertc (l, cpl[i]);
  255.           if (c == 1)
  256.         insertc (l, ' ');
  257.           else
  258.         c_bell ();
  259.           continue;
  260.         }
  261. #endif
  262.       do
  263.         if (C < L && l->overtype)
  264.           ++C, c_goright ();
  265.         else
  266.           insertc (l, ' ');
  267.       while (C % 8 != 0);
  268.       break;
  269.     case 'D' - '@':
  270.     case EKEY_kr:
  271.       if (C == L)
  272.         {
  273.           c_bell ();
  274.           break;
  275.         }
  276.       c_goright ();
  277.       C++;
  278.       break;
  279.     case 'S' - '@':
  280.     case EKEY_kl:
  281.       if (C == 0)
  282.         {
  283.           c_bell ();
  284.           break;
  285.         }
  286.       c_goleft ();
  287.       C--;
  288.       break;
  289.     case 'A' - '@':
  290.       while (C && P[C - 1] == ' ')
  291.         c_goleft (), C--;
  292.       while (C && P[C - 1] != ' ')
  293.         c_goleft (), C--;
  294.       break;
  295.     case 'F' - '@':
  296.       while (C < L && P[C] != ' ')
  297.         c_goright (), C++;
  298.       while (C < L && P[C] == ' ')
  299.         c_goright (), C++;
  300.       break;
  301.     case EKEY_kb:
  302.     case '\x7F':
  303.     case 'H' - '@':
  304.       if (C == 0)
  305.         {
  306.           c_bell ();
  307.           break;
  308.         }
  309.       C--;
  310.       c_goleft ();
  311.       if (l->overtype)
  312.         {
  313.           c_putc_printable (P[C] = ' ');
  314.           c_goleft ();
  315.           break;
  316.         }
  317.     case EKEY_kD:
  318.     case 'G' - '@':
  319.       if (C == L)
  320.         {
  321.           c_bell ();
  322.           break;
  323.         }
  324.       for (i = C; ++i < L;)
  325.         c_putc_printable (P[i - 1] = P[i]);
  326.       c_putc_printable (' ');
  327.       left (i - C);
  328.       L--;
  329.       break;
  330.     case EKEY_kI:
  331.     case 'V' - '@':
  332.       l->overtype = !l->overtype;
  333.       continue;
  334.     case 'C' - '@':
  335.       l->caps = !l->caps;
  336.       continue;
  337.     case EKEY_ku:
  338.     case 'E' - '@':
  339.       if (!H || !back_history (l))
  340.         c_bell ();
  341.       break;
  342.     case EKEY_kd:
  343.     case 'X' - '@':
  344.       if (!H || !fwd_history (l))
  345.         c_bell ();
  346.       break;
  347.     case EKEY_kh:
  348.       left (C);
  349.       C = 0;
  350.       break;
  351.     case EKEY_kH:
  352.       right (L - C);
  353.       C = L;
  354.       break;
  355.     case 'Q' - '@':
  356.       switch (toupper (c_getkey ()) | '@')
  357.         {
  358.         case 'S':
  359.           left (C);
  360.           C = 0;
  361.           break;
  362.         case 'D':
  363.           right (L - C);
  364.           C = L;
  365.           break;
  366.         default:
  367.           c_bell ();
  368.         }
  369.       break;
  370.     case 'U' - '@':
  371.       replace_string (l, "");
  372.       return 0;
  373.     case 'J' - '@':
  374.     case 'M' - '@':
  375. /*      case EKEY_enter:
  376.  */ goto end;
  377.     }
  378.       display = 0;
  379.       dflt = NULL;
  380.     }
  381. end:
  382.   right (L - C);
  383.   P[L] = '\0';
  384.   if (H && L > 0)
  385.     put_history_string (l, P);
  386.   memcpy (b, P, L + 1);        /* copy scratchpad to output string */
  387.   P = b;            /* restore pointer to original area */
  388.   return 1;
  389. }
  390.